
<!DOCTYPE html>
<html lang="zh-CN" class="loading">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>游戏服务器学习 - 浪子之心</title>
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="google" content="notranslate" />
    <meta name="keywords" content="Blog,"> 
    <meta name="description" content="MrChen Bolg,游戏大厅棋牌类大厅
MMORPG大厅
大厅功能（1）服务器启动，等待客户端连入
（2）维护一个当前所有连入的客户端的数据列表，数据内容包含IP地址，名字等。
（3）如果客户端创建了一个游戏服务(房间,"> 
    <meta name="author" content="Jack Chen"> 
    <link rel="alternative" href="atom.xml" title="浪子之心" type="application/atom+xml"> 
    <link rel="icon" href="/blog/img/favicon.png"> 
    
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css">

    
<link rel="stylesheet" href="/blog/css/diaspora.css">

<meta name="generator" content="Hexo 5.4.1"><link rel="stylesheet" href="/blog/css/prism.css" type="text/css"></head>

<body class="loading">
    <span id="config-title" style="display:none">浪子之心</span>
    <div id="loader"></div>
    <div id="single">
    <div id="top" style="display: block;">
    <div class="bar" style="width: 0;"></div>
    <a class="iconfont icon-home image-icon" href="javascript:;" data-url="https://mrchenlearnspace.github.io/blog"></a>
    <div title="播放/暂停" class="iconfont icon-play"></div>
    <h3 class="subtitle">游戏服务器学习</h3>
    <div class="social">
        <div>
            <div class="share">
                <a title="获取二维码" class="iconfont icon-scan" href="javascript:;"></a>
            </div>
            <div id="qr"></div>
        </div>
    </div>
    <div class="scrollbar"></div>
</div>

    <div class="section">
        <div class="article">
    <div class='main'>
        <h1 class="title">游戏服务器学习</h1>
        <div class="stuff">
            <span>十一月 06, 2022</span>
            
  <ul class="post-tags-list" itemprop="keywords"><li class="post-tags-list-item"><a class="post-tags-list-link" href="/blog/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/" rel="tag">服务器</a></li></ul>


        </div>
        <div class="content markdown">
            <h1 id="游戏大厅"><a href="#游戏大厅" class="headerlink" title="游戏大厅"></a>游戏大厅</h1><p>棋牌类大厅</p>
<p>MMORPG大厅</p>
<h1 id="大厅功能"><a href="#大厅功能" class="headerlink" title="大厅功能"></a>大厅功能</h1><p>（1）服务器启动，等待客户端连入</p>
<p>（2）维护一个当前所有连入的客户端的数据列表，数据内容包含IP地址，名字等。</p>
<p>（3）如果客户端创建了一个游戏服务(房间)，则把该游戏服务加入到一个列表中，并向其他客户端刷新列表数据,触发该客户端成为游戏的主机。<br>（4）当有客户端选择加入某个游戏服务时,帮助它连接到主机。</p>
<p>（5）维护当前所有游戏服务的参加游戏人数、游戏是否已经开始等相关信息，这些信息由服务器向建立服务的主机玩家获取。<br>（6）当一场游戏结束后，服务器从主机玩家那里获取游戏结果和分数等信息，并更新排行榜。</p>
<h1 id="服务器热更"><a href="#服务器热更" class="headerlink" title="服务器热更"></a>服务器热更</h1><h2 id="当引用无依赖的库"><a href="#当引用无依赖的库" class="headerlink" title="当引用无依赖的库"></a>当引用无依赖的库</h2><p>Dll生成库代码</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> System;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">ClassLibrary1</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">class</span> <span class="title">Class1</span> &#123;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span>()</span> &#123;</span><br><span class="line">            Console.WriteLine(<span class="string">&quot;uuuuuuuuu&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>服务器部分</strong><br>CodeLoader.cs</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> System;</span><br><span class="line"><span class="keyword">using</span> System.Collections.Generic;</span><br><span class="line"><span class="keyword">using</span> System.IO;</span><br><span class="line"><span class="keyword">using</span> System.Reflection;</span><br><span class="line"><span class="keyword">using</span> System.Runtime.Loader;</span><br><span class="line"><span class="keyword">using</span> System.Text;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">MMONetworkServer</span> &#123;</span><br><span class="line">    <span class="keyword">class</span> <span class="title">CodeLoader</span> &#123;</span><br><span class="line">        AssemblyLoadContext assemblyLoadContext;</span><br><span class="line">        Assembly hotfix;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">Reload</span>()</span> &#123;</span><br><span class="line">            assemblyLoadContext?.Unload();</span><br><span class="line">            GC.Collect();</span><br><span class="line">            assemblyLoadContext = <span class="keyword">new</span> AssemblyLoadContext(<span class="string">&quot;ClassLibrary1&quot;</span>, <span class="literal">true</span>);</span><br><span class="line">            <span class="built_in">byte</span>[] dllBytes = File.ReadAllBytes(<span class="string">@&quot;F:\project\VSProject\ClassLibrary1\bin\Debug\netcoreapp3.1\ClassLibrary1.dll&quot;</span>);<span class="comment">//加载dll</span></span><br><span class="line">            <span class="built_in">byte</span>[] pdbBytes = File.ReadAllBytes(<span class="string">@&quot;F:\project\VSProject\ClassLibrary1\bin\Debug\netcoreapp3.1\ClassLibrary1.pdb&quot;</span>);<span class="comment">//加载pdb</span></span><br><span class="line">            hotfix = assemblyLoadContext.LoadFromStream(<span class="keyword">new</span> MemoryStream(dllBytes), <span class="keyword">new</span> MemoryStream(pdbBytes));</span><br><span class="line">            <span class="built_in">object</span> obj = hotfix.CreateInstance(<span class="string">&quot;ClassLibrary1.Class1&quot;</span>);</span><br><span class="line">            MethodInfo mm = obj.GetType().GetMethod(<span class="string">&quot;add&quot;</span>);</span><br><span class="line">            mm.Invoke(obj, <span class="literal">null</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>Main.cs</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">using</span> System;</span><br><span class="line"><span class="keyword">using</span> System.IO;</span><br><span class="line"><span class="keyword">using</span> System.Reflection;</span><br><span class="line"><span class="keyword">using</span> System.Runtime.Loader;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">MMONetworkServer</span> &#123;</span><br><span class="line">    <span class="keyword">class</span> <span class="title">Program</span> &#123;</span><br><span class="line">        <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span>(<span class="params"><span class="built_in">string</span>[] args</span>)</span> &#123;</span><br><span class="line"></span><br><span class="line">            CodeLoader codeLoader = <span class="keyword">new</span> CodeLoader();</span><br><span class="line">            <span class="keyword">while</span>(<span class="literal">true</span>) &#123;</span><br><span class="line">                Console.ReadLine();</span><br><span class="line">                codeLoader.Reload();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>运行后修改add函数然后生成新的dll，让main重载。</p>
<p>运用到游戏，思路逻辑写入热更项目中，非热更部分做好接口，通过反射创建实例。</p>
<h2 id="思路2"><a href="#思路2" class="headerlink" title="思路2"></a>思路2</h2><p>让热更项目依赖于总项目，然后总项目调用热更新部分时使用反射来获取相关实例。<br>CodeLoader.cs</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> System;</span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> System.Collections.Generic;</span><br><span class="line"><span class="keyword">using</span> System.IO;</span><br><span class="line"><span class="keyword">using</span> System.Reflection;</span><br><span class="line"><span class="keyword">using</span> System.Runtime.Loader;</span><br><span class="line"><span class="keyword">using</span> System.Text;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">MMONetworkServer.Core</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">class</span> <span class="title">CodeLoader</span>  &#123;</span><br><span class="line">        AssemblyLoadContext assemblyLoadContext;</span><br><span class="line">        Assembly hotfix;</span><br><span class="line">        Dictionary&lt;<span class="built_in">string</span>, <span class="built_in">object</span>&gt; hotfixInstance = <span class="keyword">new</span> Dictionary&lt;<span class="built_in">string</span>, <span class="built_in">object</span>&gt;();</span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">static</span> CodeLoader instance ;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">CodeLoader</span>()</span> &#123;</span><br><span class="line">            </span><br><span class="line">                instance = <span class="keyword">this</span>;</span><br><span class="line">            </span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> CodeLoader <span class="title">GetInstance</span>()</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> instance;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">Reload</span>()</span> &#123;</span><br><span class="line">            hotfixInstance.Clear();</span><br><span class="line">            assemblyLoadContext?.Unload();</span><br><span class="line">            GC.Collect();</span><br><span class="line">            assemblyLoadContext = <span class="keyword">new</span> AssemblyLoadContext(<span class="string">&quot;ClassLibrary1&quot;</span>, <span class="literal">true</span>);</span><br><span class="line">            <span class="built_in">byte</span>[] dllBytes = File.ReadAllBytes(<span class="string">@&quot;F:\project\VSProject\ClassLibrary1\bin\Debug\netcoreapp3.1\ClassLibrary1.dll&quot;</span>);<span class="comment">//加载dll</span></span><br><span class="line">            <span class="built_in">byte</span>[] pdbBytes = File.ReadAllBytes(<span class="string">@&quot;F:\project\VSProject\ClassLibrary1\bin\Debug\netcoreapp3.1\ClassLibrary1.pdb&quot;</span>);<span class="comment">//加载pdb</span></span><br><span class="line">            hotfix = assemblyLoadContext.LoadFromStream(<span class="keyword">new</span> MemoryStream(dllBytes), <span class="keyword">new</span> MemoryStream(pdbBytes));</span><br><span class="line">            <span class="comment">//object obj = hotfix.CreateInstance(&quot;ClassLibrary1.Class1&quot;);</span></span><br><span class="line">            <span class="comment">//MethodInfo mm = obj.GetType().GetMethod(&quot;add&quot;);</span></span><br><span class="line">            <span class="comment">//mm.Invoke(obj, null);</span></span><br><span class="line"></span><br><span class="line">            <span class="keyword">foreach</span>(Type type <span class="keyword">in</span> hotfix.GetTypes()) &#123;</span><br><span class="line">                <span class="built_in">object</span> instance = Activator.CreateInstance(type);</span><br><span class="line">                hotfixInstance.Add(type.FullName, instance);</span><br><span class="line">                Console.WriteLine(type.FullName);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="built_in">object</span> <span class="title">Find</span>(<span class="params"><span class="built_in">string</span> className</span>)</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> hotfixInstance[className];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">FindFunRun</span>(<span class="params"><span class="built_in">string</span> className,<span class="built_in">string</span> funName,<span class="built_in">object</span>[] objs</span>)</span> &#123;</span><br><span class="line">            MethodInfo mm = Find(className).GetType().GetMethod(funName);</span><br><span class="line">            mm.Invoke(Find(className), objs);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>当总项目使用热更部分时</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">HandleMsg</span>(<span class="params">Conn conn, ProtocolBase protoBase</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">string</span> name = protoBase.GetName();</span><br><span class="line">    <span class="built_in">string</span> methodName = <span class="string">&quot;Msg&quot;</span> + name;</span><br><span class="line">    <span class="comment">//连接协议分发</span></span><br><span class="line">    <span class="keyword">if</span> (conn.player == <span class="literal">null</span> || name == <span class="string">&quot;HeatBeat&quot;</span> || name == <span class="string">&quot;Logout&quot;</span>) &#123;</span><br><span class="line">        MethodInfo mm = CodeLoader.GetInstance().Find(<span class="string">&quot;MMONetworkServer.Logic.HandleConnMsg&quot;</span>).GetType().GetMethod(methodName);</span><br><span class="line">        <span class="keyword">if</span> (mm == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="built_in">string</span> str = <span class="string">&quot;[警告]HandleMsg没有处理连接方法 &quot;</span>;</span><br><span class="line">            Console.WriteLine(str + methodName);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        Object[] obj = <span class="keyword">new</span> <span class="built_in">object</span>[] &#123; conn, protoBase &#125;;</span><br><span class="line">        Console.WriteLine(<span class="string">&quot;[处理连接消息]&quot;</span> + conn.GetAdress() + <span class="string">&quot; :&quot;</span> + name);</span><br><span class="line">        mm.Invoke(CodeLoader.GetInstance().Find(<span class="string">&quot;MMONetworkServer.Logic.HandleConnMsg&quot;</span>), obj);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//角色协议分发</span></span><br><span class="line">    <span class="keyword">else</span> &#123;</span><br><span class="line">        MethodInfo mm = CodeLoader.GetInstance().Find(<span class="string">&quot;MMONetworkServer.Logic.HandlePlayerMsg&quot;</span>).GetType().GetMethod(methodName);</span><br><span class="line">        <span class="keyword">if</span> (mm == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="built_in">string</span> str = <span class="string">&quot;[警告]HandleMsg没有处理玩家方法&quot;</span>;</span><br><span class="line">        Console.WriteLine(str + methodName);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        Object[] obj = <span class="keyword">new</span> <span class="built_in">object</span>[] &#123; conn.player, protoBase &#125;;</span><br><span class="line">        Console.WriteLine(<span class="string">&quot;[处理玩家消息]&quot;</span> + conn.player.id + <span class="string">&quot; :&quot;</span> + name);</span><br><span class="line">        mm.Invoke(CodeLoader.GetInstance().Find(<span class="string">&quot;MMONetworkServer.Logic.HandlePlayerMsg&quot;</span>), obj);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>事件部分因为依赖于总项目所以能直接编译。</p>
<h2 id="对于反射部分的优化"><a href="#对于反射部分的优化" class="headerlink" title="对于反射部分的优化"></a>对于反射部分的优化</h2><p>使用委托来完成。<a target="_blank" rel="noopener" href="https://focus-creative-games.github.io/hybridclr/best_practices/#%E7%83%AD%E6%9B%B4%E6%96%B0%E5%B1%82%E8%BF%94%E5%9B%9E%E4%B8%80%E4%B8%AA-delegate">学习渠道参考文章</a>   <a target="_blank" rel="noopener" href="http://www.zkea.net/blog/detail/csharp-fast-get-property-value.html">性能测试</a>  </p>
<h3 id="反射"><a href="#反射" class="headerlink" title="反射"></a>反射</h3><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//HandleConnMsg</span></span><br><span class="line">MethodInfo mm = CodeLoader.GetInstance().Find(<span class="string">&quot;MMONetworkServer.Logic.HandleConnMsg&quot;</span>).GetType().GetMethod(methodName);</span><br><span class="line">Object[] obj = <span class="keyword">new</span> <span class="built_in">object</span>[] &#123; conn, protoBase &#125;;</span><br><span class="line">mm.Invoke(CodeLoader.GetInstance().Find(<span class="string">&quot;ServerLoginHotfix.HandleConnMsg&quot;</span>), obj);</span><br><span class="line"><span class="comment">//HandlePlayerMsg</span></span><br><span class="line">MethodInfo mm = CodeLoader.GetInstance().Find(<span class="string">&quot;MMONetworkServer.Logic.HandlePlayerMsg&quot;</span>).GetType().GetMethod(methodName);</span><br><span class="line">Object[] obj = <span class="keyword">new</span> <span class="built_in">object</span>[] &#123; conn.player, protoBase &#125;;</span><br><span class="line">Console.WriteLine(<span class="string">&quot;[处理玩家消息]&quot;</span> + conn.player.id + <span class="string">&quot; :&quot;</span> + name);</span><br></pre></td></tr></table></figure>

<h3 id="委托"><a href="#委托" class="headerlink" title="委托"></a>委托</h3><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//HandleConnMsg</span></span><br><span class="line">MethodInfo mm = CodeLoader.GetInstance().Find(<span class="string">&quot;MMONetworkServer.Logic.HandleConnMsg&quot;</span>).GetType().GetMethod(methodName);</span><br><span class="line">Action&lt;Conn, ProtocolBase&gt; updateDel = (Action&lt;Conn,ProtocolBase&gt;)Delegate.CreateDelegate(<span class="keyword">typeof</span>(Action&lt;Conn, ProtocolBase&gt;), <span class="literal">null</span>, mm);</span><br><span class="line">updateDel(conn, protoBase);</span><br><span class="line"><span class="comment">//HandlePlayerMsg</span></span><br><span class="line">MethodInfo mm = CodeLoader.GetInstance().Find(<span class="string">&quot;MMONetworkServer.Logic.HandleConnMsg&quot;</span>).GetType().GetMethod(methodName);</span><br><span class="line">Action&lt;IPlayer, ProtocolBase&gt; updateDel = (Action&lt;IPlayer, ProtocolBase&gt;)Delegate.CreateDelegate(<span class="keyword">typeof</span>(Action&lt;IPlayer, ProtocolBase&gt;), <span class="literal">null</span>, mm);</span><br><span class="line">updateDel(conn.player, protoBase);</span><br></pre></td></tr></table></figure>

<h3 id="比较"><a href="#比较" class="headerlink" title="比较"></a>比较</h3><h4 id="运行速度"><a href="#运行速度" class="headerlink" title="运行速度"></a>运行速度</h4><p>虽然上面参考文章上写着委托比反射快，但我测试数据如下</p>
<table>
<thead>
<tr>
<th>反射</th>
<th>委托</th>
</tr>
</thead>
<tbody><tr>
<td>[处理玩家消息] Time: 00:00:00.188 3370</td>
<td>[处理玩家消息] Time: 00:00:00.188 6885</td>
</tr>
<tr>
<td>[处理玩家消息] Time: 00:00:00.022 5805</td>
<td>[处理玩家消息] Time: 00:00:00.023 2066</td>
</tr>
<tr>
<td>[处理玩家消息] Time: 00:00:00.010 5767</td>
<td>[处理玩家消息] Time: 00:00:00.006 4742</td>
</tr>
<tr>
<td>[处理玩家消息] Time: 00:00:00.000 7305</td>
<td>[处理玩家消息] Time: 00:00:00.000 8893</td>
</tr>
<tr>
<td>[处理玩家消息] Time: 00:00:00.005 2011</td>
<td>[处理玩家消息] Time: 00:00:00.005 4224</td>
</tr>
<tr>
<td>[处理玩家消息] Time: 00:00:00.000 6916</td>
<td>[处理玩家消息] Time: 00:00:00.000 7680</td>
</tr>
</tbody></table>
<p>可能是因为我在codeloader读取数据集时将所有类进行了实例化，因此加快了反射的速度。</p>
<h4 id="内存开销"><a href="#内存开销" class="headerlink" title="内存开销"></a>内存开销</h4><p>委托会比反射造成内存开销小，因为舍去了将运行参数装箱拆箱的过程，减少了内存gc。</p>
<h4 id="热更类的变化"><a href="#热更类的变化" class="headerlink" title="热更类的变化"></a>热更类的变化</h4><ol>
<li><p>委托方法调用方法及方法内使用的变量和参数的逻辑类将进行静态处理否则将会委托绑定不到具体对象。例如</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">partial</span> <span class="keyword">class</span> <span class="title">HandleConnMsg</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">static</span> HandlePlayerEvent handlePlayerEvent = <span class="keyword">new</span> HandlePlayerEvent();</span><br><span class="line">        <span class="keyword">static</span> LogicManager logicManager;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">MsgHeatBeat</span>(<span class="params">Conn conn, ProtocolBase protoBase</span>)</span> &#123;</span><br><span class="line">            conn.lastTickTime = Sys.GetTimeStamp();</span><br><span class="line">            Console.WriteLine(<span class="string">&quot;[更新心跳时间]&quot;</span> + conn.GetAdress());</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


</li>
<li><p>委托的具体参数一定要一致，不能为某个类的子类，否则会委托与具体函数签名不一致。</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">partial</span> <span class="keyword">class</span> <span class="title">HandlePlayerMsg</span> &#123;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">MsgWWWW</span>(<span class="params">IPlayer iplayer, ProtocolBase protoBase</span>)</span> &#123;</span><br><span class="line">           Console.WriteLine(<span class="string">&quot;wwwwwww&quot;</span>);</span><br><span class="line">       &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​    反射可以直接写为player，但委托要与委托变量一致</p>
</li>
</ol>
<p>​    </p>

            <!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->
            <audio id="audio" loop="1" preload="auto" controls="controls" data-autoplay="false">
                <source type="audio/mpeg" src="/music/jucilang.mp3">
            </audio>
            
        </div>
        
    <div id='gitalk-container' class="comment link"
		data-enable='true'
        data-ae='true'
        data-ci='99f95a936c6fcdb1bd67'
        data-cs='c2d1bba3d6b7f9ade4f3de09a63925bd837c25ea'
        data-r='mrchenlearnspace.github.io'
        data-o='MrChenLearnSpace'
        data-a='MrChenLearnSpace'
        data-d='false'
    >查看评论</div>


    </div>
    
        <div class='side'>
			<ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E6%B8%B8%E6%88%8F%E5%A4%A7%E5%8E%85"><span class="toc-number">1.</span> <span class="toc-text">游戏大厅</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%A4%A7%E5%8E%85%E5%8A%9F%E8%83%BD"><span class="toc-number">2.</span> <span class="toc-text">大厅功能</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%83%AD%E6%9B%B4"><span class="toc-number">3.</span> <span class="toc-text">服务器热更</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%BD%93%E5%BC%95%E7%94%A8%E6%97%A0%E4%BE%9D%E8%B5%96%E7%9A%84%E5%BA%93"><span class="toc-number">3.1.</span> <span class="toc-text">当引用无依赖的库</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%9D%E8%B7%AF2"><span class="toc-number">3.2.</span> <span class="toc-text">思路2</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AF%B9%E4%BA%8E%E5%8F%8D%E5%B0%84%E9%83%A8%E5%88%86%E7%9A%84%E4%BC%98%E5%8C%96"><span class="toc-number">3.3.</span> <span class="toc-text">对于反射部分的优化</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8F%8D%E5%B0%84"><span class="toc-number">3.3.1.</span> <span class="toc-text">反射</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A7%94%E6%89%98"><span class="toc-number">3.3.2.</span> <span class="toc-text">委托</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%AF%94%E8%BE%83"><span class="toc-number">3.3.3.</span> <span class="toc-text">比较</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%BF%90%E8%A1%8C%E9%80%9F%E5%BA%A6"><span class="toc-number">3.3.3.1.</span> <span class="toc-text">运行速度</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%86%85%E5%AD%98%E5%BC%80%E9%94%80"><span class="toc-number">3.3.3.2.</span> <span class="toc-text">内存开销</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%83%AD%E6%9B%B4%E7%B1%BB%E7%9A%84%E5%8F%98%E5%8C%96"><span class="toc-number">3.3.3.3.</span> <span class="toc-text">热更类的变化</span></a></li></ol></li></ol></li></ol></li></ol>	
        </div>
    
</div>


    </div>
</div>
</body>

<script src="//cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>


<script src="//lib.baomitu.com/jquery/1.8.3/jquery.min.js"></script>
<script src="/blog/js/plugin.js"></script>
<script src="/blog/js/typed.js"></script>
<script src="/blog/js/diaspora.js"></script>


<link rel="stylesheet" href="/blog/photoswipe/photoswipe.css">
<link rel="stylesheet" href="/blog/photoswipe/default-skin/default-skin.css">


<script src="/blog/photoswipe/photoswipe.min.js"></script>
<script src="/blog/photoswipe/photoswipe-ui-default.min.js"></script>


<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">
                <!--  Controls are self-explanatory. Order can be changed. -->
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>



<script type="text/x-mathjax-config">
    MathJax.Hub.Config({"HTML-CSS": { preferredFont: "TeX", availableFonts: ["STIX","TeX"], linebreaks: { automatic:true }, EqnChunk: (MathJax.Hub.Browser.isMobile ? 10 : 50) },
        tex2jax: { inlineMath: [ ["$", "$"], ["\\(","\\)"] ], processEscapes: true, ignoreClass: "tex2jax_ignore|dno",skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']},
        TeX: {  noUndefined: { attributes: { mathcolor: "red", mathbackground: "#FFEEEE", mathsize: "90%" } }, Macros: { href: "{}" } },
        messageStyle: "none"
    });
</script>
<script type="text/x-mathjax-config">
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for(i=0; i < all.length; i += 1) {
            all[i].SourceElement().parentNode.className += ' has-jax';
        }
    });
</script>

<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>



<!-- Google Analytics -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-YMJ8CBH8F7"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-YMJ8CBH8F7');
</script>
<!-- End Google Analytics -->


</html>
